using UnityEngine;

//怪物类
public class Enemy : GameBehavior
{
    EnemyFactory _originFactory;

    //追踪两个瓦片及其位置
    GameTile tileFrom, tileTo;
    Vector3 positionFrom, positionTo;
    //追踪方向，方向变化以及必须在其间进行插值的角度
    Direction direction;
    DirectionChange directionChange;
    float directionAngleFrom, directionAngleTo;
    //追踪进度
    float progress;
    //进度因子，用来缩放GameUpdate中的增量
    float progressFactor;

    [SerializeField]
    Transform model = default;

    //动画引用
    [SerializeField]
    EnemyAnimationConfig animationConfig = default;

    //路径偏移
    float pathOffset;

    //速度
    float speed;

    //缩放
    public float Scale{get; private set;}

    //生命
    float Health {get; set;}

    //动画播放器
    EnemyAnimator animator;

    //判断是否是有效目标（移动中的目标才是可攻击的）
    public bool IsValidTarget => animator.CurrentClip == Clip.Move;

    //碰撞器
    Collider targetPointCollider;

    public Collider TargetPointCollider
    {
        set
        {
            Debug.Assert(targetPointCollider == null, "Redefined collider!");
            targetPointCollider = value;
        }
    }


    //设置工厂
    public EnemyFactory OriginFactory
    {
        get => _originFactory;
        set{
            Debug.Assert(_originFactory == null , "Redefined origin factory!");
            _originFactory = value;
        }
    }

    void Awake()
    {
        animator.Configure(
            //给每个敌人添加一个Animator组件为第一个子节点
            model.GetChild(0).gameObject.AddComponent<Animator>(),
            animationConfig
        );
    }

    //初始化 设置缩放 设置速度 设置路径偏移
    public void Initialize(float scale, float speed, float pathOffset, float health)
    {
        Scale = scale;
        model.localScale = new Vector3(scale, scale, scale);
        this.pathOffset = pathOffset;
        this.speed = speed;
        Health = health;
        animator.PlayIntro();
        //从播放intro开始，禁用碰撞器
        targetPointCollider.enabled = false;
    }

    //设置位置
    public void SpawnOn(GameTile tile)
    {
        Debug.Assert(tile.NextTileOnPath != null,"Nowhere to go!", this);
        tileFrom = tile;
        tileTo = tile.NextTileOnPath;
        progress = 0f;
        PrepareIntro();
    }

    //设置初始状态
    void PrepareIntro()
    {
        positionFrom = tileFrom.transform.localPosition;
        transform.localPosition = positionFrom;
        positionTo = tileFrom.ExitPoint;
        direction = tileFrom.PathDirection;
        directionChange = DirectionChange.None;
        directionAngleFrom = directionAngleTo = direction.GetAngle();
        model.localPosition = new Vector3(pathOffset, 0f);
        transform.localRotation = tileFrom.PathDirection.GetRotation();//在生成瓦片的时候旋转敌人
        
        progressFactor =speed;//仅仅覆盖一半的瓦片，因此其进度也应加倍以保持速度恒定
    }

    //设置结束状态，设置向前移动，但仅向瓦片中心移动，并加倍进度以保持速度恒定。
    void PrepareOutro()
    {
        positionTo = tileFrom.transform.localPosition;
        directionChange = DirectionChange.None;
        directionAngleTo = direction.GetAngle();
        model.localPosition = new Vector3(pathOffset, 0f);
        transform.localRotation = direction.GetRotation();
        progressFactor = speed;
    }

    //刷新位置
    public override bool GameUpdate()
    {
        animator.GameUpdate();
        if(animator.CurrentClip == Clip.Intro)
        {
            if(!animator.IssDone)
                return true;
            animator.PlayMove(speed / Scale);
            //只有移动时启用碰撞器
            targetPointCollider.enabled = true;
        }else if(animator.CurrentClip >= Clip.Outro)
        {
            if(animator.IssDone)
            {
                Recycle();
                return false;
            }
            return true;
        }

        if(Health <= 0f)
        {//生命值为0,播放死亡动画
            animator.PlayDying();
            targetPointCollider.enabled = false;
            return true;
        }

        //每秒移动一格然后刷新跟踪的两个瓦片数据
        progress += Time.deltaTime * progressFactor;
        while(progress >= 1f)
        {
            if(tileTo == null)
            {//已经到达终点
                
                Game.EnemyReachedDestination();
                animator.PlayOutro();
                targetPointCollider.enabled = false;
                return true;
            }
            progress = (progress - 1f) / progressFactor;
            PrepareNextState();
            progress *= progressFactor;
        }
        if(directionChange == DirectionChange.None)
        {   
            transform.localPosition = Vector3.LerpUnclamped(positionFrom, positionTo, progress);
        }else{//当方向改变时，不能完全插入位置，因为移动是通过旋转来完成的。
            float angle = Mathf.LerpUnclamped(directionAngleFrom, directionAngleTo, progress);
            transform.localRotation = Quaternion.Euler(0f, angle, 0f);
        }
            
        return true;
    }

    void PrepareNextState()
    {
        tileFrom = tileTo;
        tileTo = tileTo.NextTileOnPath;
        positionFrom = positionTo;
        if(tileTo == null){
            PrepareOutro();
            return;
        }
        positionTo = tileFrom.ExitPoint;
        directionChange = direction.GetDirectionChangeTo(tileFrom.PathDirection);
        direction = tileFrom.PathDirection;
        directionAngleFrom = directionAngleTo;
        switch(directionChange)
        {
            case DirectionChange.None:
                PrepareForward();
                break;
            case DirectionChange.TurnRight:
                PrepareTurnRight();
                break;
            case DirectionChange.TurnLeft:
                PrepareTurnLeft();
                break;
            case DirectionChange.TurnAround:
                PrepareTurnAround();
                break;
            
        }
    }

    void PrepareForward()
    {
        transform.localRotation = direction.GetRotation();
        directionAngleTo = direction.GetAngle();
        model.localPosition = new Vector3(pathOffset, 0f);//前进时模型设置为默认位置，位于敌人的本地位置
        progressFactor = speed;//前进状态不需要任何改变，因此使用系数1
    }
    void PrepareTurnRight(){
        directionAngleTo = directionAngleFrom + 90f;
        model.localPosition = new Vector3(pathOffset - 0.5f, 0f);//转弯时，模型需要从旋转点偏移半个单位（旋转圆的半径）
        transform.localPosition = positionFrom + direction.GetHalfVector();//转弯时添加适当的向量
        progressFactor = speed / (Mathf.PI * 0.5f * (0.5f - pathOffset));//转弯时，敌人覆盖了半径为0.5的四分之一圆，因此覆盖距离是0.25π
    }
    void PrepareTurnLeft(){
        directionAngleTo = directionAngleFrom - 90f;
        model.localPosition = new Vector3(pathOffset + 0.5f, 0f);//转弯时，模型需要从旋转点偏移半个单位（旋转圆的半径）
        transform.localPosition = positionFrom + direction.GetHalfVector();
        progressFactor = speed / (Mathf.PI * 0.5f * (0.5f + pathOffset));//转弯时，敌人覆盖了半径为0.5的四分之一圆，因此覆盖距离是0.25π
    }
    void PrepareTurnAround(){
        directionAngleTo = directionAngleFrom + (pathOffset < 0f ? 180f : -180f);
        model.localPosition = new Vector3(pathOffset, 0f);//前进时模型设置为默认位置，位于敌人的本地位置
        transform.localPosition = positionFrom;//
        progressFactor = speed / (Mathf.PI *Mathf.Max(Mathf.Abs(pathOffset), 0.2f));
    }

    public void ApplyDamage(float damage)
    {
        Debug.Assert(damage >= 0f,"Negative damage applied.");
        Health -= damage;
    }

    public override void Recycle()
    {
        animator.Stop();
        OriginFactory.Reclaim(this);
    }

    void OnDestroy()
    {
        animator.Destroy();
    }

}